package org.zn.note.designpattern;

/**
 * 单例模式（Singleton Pattern）
 * 饿汉：提前创建，没有线程安全问题。有可能没用到但是实例化了，占内存。
 * 懒汉：用时创建，有线程安全问题（lazy loading）
 */
public class Pattern03_Singleton {

    // 饿汉：提前创建
    private static class SingleObject {
        // 创建 SingleObject 的一个对象
        private static SingleObject instance = new SingleObject();

        private SingleObject() {
        }

        // 获取唯一可用的对象
        public static SingleObject getInstance() {
            return instance;
        }
    }

    // 懒汉一：线程不安全，可能创建多个实例
    private static class Singleton1 {
        private static Singleton1 instance;

        private Singleton1() {
        }

        public static Singleton1 getInstance() {
            if (instance == null) {
                instance = new Singleton1();
            }
            return instance;
        }
    }

    // 懒汉二：线程安全，能保证只有一个实例，但效率低
    private static class Singleton2 {
        private static Singleton2 instance;

        private Singleton2() {
        }

        public static synchronized Singleton2 getInstance() {
            if (instance == null) {
                instance = new Singleton2();
            }
            return instance;
        }
    }

    // 懒汉三：双检锁/双重校验锁（DCL，即 double-checked locking）
    private static class Singleton3 {
        private volatile static Singleton3 singleton;

        private Singleton3() {
        }

        public static Singleton3 getSingleton() {
            if (singleton == null) {
                synchronized (Singleton3.class) {
                    if (singleton == null) {
                        singleton = new Singleton3();
                    }
                }
            }
            return singleton;
        }
    }

    // 懒汉四：登记式/静态内部类
    private static class Singleton4 {
        private static class SingletonHolder {
            private static final Singleton4 INSTANCE = new Singleton4();
        }

        private Singleton4() {
        }

        public static final Singleton4 getInstance() {
            return SingletonHolder.INSTANCE;
        }
    }

    // 懒汉五：枚举
    private enum Singleton5 {
        INSTANCE;
        public void whateverMethod() {
        }
    }
}
